### Списки I
1. Реализуйте контейнер в виде шаблона класса ```ForwardList```. Поддержите реализацию соответствующих итератаров для этого контейнера
```cpp
template< typename T >
class ForwardList
{
  ...
};
```
Разрабатывемый интерфейс класса должен быть безопасным.

2. Ниже приведён интерфейс шаблона класса «Словарь»
```cpp
template< typename Key, typename Value, typename Compare >
class Dictionary
{
  public:
    void push(Key k, Value v);
    Value get(Key k);
    Value drop(Key k);
    ...
};
```
Словарь позволяет добавлять элементы типа ```Value``` по ключю типа ```Key```. Отношение порядка на
множестве объектов типа Key устанавливается компаратором Compare. Переработайте интерфейс: исправьте и дополните его; сделайте безопасным. Данные словаря должны храниться внутри ```ForwardList```.
Учтите, что данные внутри словаря должны быть упорядочены

3. Параметром командной строки задётся имя файла ```filename```, который содержит внутри себя данные
по некоторому количеству словарей.
Файл со словарями имеет следующий вид:
```txt
<dataset-1> <key-1-1> <value-1-1> <key-1-2> <value-1-2> ...
<dataset-2> <key-2-2> <value-2-2> <key-2-2> <value-2-2> ...
...
```
• ```dataset``` представляет собой имя словаря; ```key``` целочисленный ключ; ```value``` значение в виде
строки соответствующее ключу Например:
```txt
first 1 name 2 surname
second 4 mouse 1 name 2 keyboard
```
• Пустые строки игнорируются. Данные в строке разделены ровно одним пробелом

4. Реализуемая программа должна считывать данные словарей из файла и выполнять команды, при-
нимаемые от пользователя со стандартного ввода.
• Каждая строка содержит ровно одну команду. Должны поддерживаться следующие команды:
```txt
print <dataset>
complement <newdataset> <dataset-1> <dataset-2>
intersect <newdataset> <dataset-1> <dataset-2>
union <newdataset> <dataset-1> <dataset-2>
```
• Команда ```print <dataset>``` выводит данные словаря с соответствующем именем в порядке сор-
тировки ключей. Например, для second должна быть напечатана строка
```txt
second 1 name 2 keyboard 4 mouse
```
Если словарь пуст, то команда должна вывести сообщение ```<EMPTY>```

• Команда ```complement <newdataset> <dataset-1> <dataset-2>``` строит словарь с новым именем
как вычитание множеств двух других словарей. Например, для команд:
```txt
complement third second first
print third
Должен быть результат:
third 4 mouse
```
• Команда ```intersect <newdataset> <dataset-1> <dataset-2>``` строит словарь с новыми именем
как пересечение множеств двух других словарей. Например, для команд:
```txt
intersect fourth first second
print fourth
```
Должен быть результат:
```txt
fourth 1 name 2 surname
```
Если ключи дублируются, в качестве значения выбираются данные из левого операнда, т. е.
для команд:
```txt
intersect yafourth second first
print yafourth
```
Должен быть результат:
```txt
yafourth 1 name 2 keyboard
```
• Команда ```union <newdataset> <dataset-1> <dataset-2>``` строит словарь с новым именем как
объединение множеств двух других словарей. Например, для команд:
```txt
union fifth first second
print fifth
```
Должен быть результат:
```txt
fifth 1 name 2 surname 4 mouse
```
Если ключи дублируются, в качестве значения выбираются данные из левого операнда, т. е.
для команд:
```txt
union yafifth second first
print yafifth
```
Должен быть результат:
```txt
yafifth 1 name 2 keyboard 4 mouse
```
• Если команда по каким-то причинам некорректна, то команда должна вывести сообщение
```<INVALID COMMAND>```
• Других команд реализовывать не требуется

• Признаком конца ввода команд является EOF (на Linux: Ctrl + D | на Windows Ctrl + C)
6. Работа должна быть выполнена в виде 1-го исполняемого файла, принимающего параметры следу-
ющим образом:
```txt
$ ./lab filename
```
```filename``` представляет собой обязательный параметр. Поведение программы меняется в зависимости
от того передан он или нет. Если параметр filename не задан, программа должна завершаться с
ненулевым кодом возврата и сообщением об ошибке

Совет-1 При реализации ```ForwardList``` следует ориентироваться на ```std::forward_list``` и его итераторы

Совет-2 Интерфейс словаря проще всего сделать безопасным, используя итераторы реализованного списка

Совет-3 Список, посредством которого будет реализован словарь, инстанцируется парой (```std::pair```), в которой первый элемент является ключом, а второй - значением списком пар ключ-значение. При
этом, для хранения словарей следует использовать словарь, где ключом являются имена словарей,
а значениями - сами словари

Совет-4 Названия команд и их конкретные реализации представимы в виде словаря
